%skeleton "lalr1.cc"
%require "2.2"
%defines

%{
#include "slak/mesh/SG3.h"
namespace yy {
	class parser_driver;
}
%}

%parse-param { yy::parser_driver& driver }
%lex-param   { yy::parser_driver& driver }

%locations
%initial-action 
{
	@$.begin.filename = @$.end.filename = &driver.file;
}

%debug
%error-verbose

%union {
	Arg * arg;
	Option * opt;
	Section * sect;
	Header * head;
}

// %{ ... %} after %union goes to .cc file (and not to .hh)
%{
#include "slak/mesh/ResourceParserDriver.h"
%}

%token		END	0	"end of file"
%token	<arg>	STRING
%token	<arg>	KEYWORD
%token	<arg>	NUMBER

%type	<arg>	arg
%type	<opt>	args
%type	<opt>	option
%type	<sect>	options
%type	<head>	header

%destructor { delete $$; } STRING KEYWORD NUMBER
%destructor { delete $$; } arg args option options header

%% 
%start rc ;

rc: resources END ;

resources: resources section
	 | /* empty */
	 ;

section: header options { driver.class_table[$1->first][$1->second] = *$2; }
       ;

header: '[' KEYWORD STRING ']' '\n' { $$ = new Header(boost::get<std::string>(*$2), boost::get<std::string>(*$3)); }
      ;

options: options option	{ $$ = $1; $$->push_back(*$2); }
       | /* empty */ 	{ $$ = new Section(); }
       ;

option: KEYWORD args '\n' { $$ = $2; $$->first = boost::get<std::string>(*$1); }
      ;

args: args arg	  { $$ = $1; $$->second.push_back(*$2); }
    | /* empty */ { $$ = new Option(); }
    ;

arg: STRING
   | NUMBER
   | KEYWORD
   ;


%%
void yy::parser::error (const yy::parser::location_type& l, 
			const std::string& m)
{
	driver.error(l, m);
}

